﻿#include "tuimgr.h"

#include <QDomDocument>
#include "../../include/itlogger.h"
#include "../../include/itframework.h"

TUiMgr::TUiMgr()
{
    m_pFramework = NULL;
    m_pUIList.clear();
    m_pModelMap.clear();
}

TUiMgr::~TUiMgr()
{

}

TRESULT TUiMgr::Init()
{
    m_pLogger->WriteLog("TUiMgr::Init()");
    QFile fileXml("module/ui.xml");
    bool bOpen = fileXml.open(QIODevice::ReadOnly | QIODevice::Text);
    if(!bOpen)
        return T_FALSE;
    QDomDocument document;
    QString strErr("");
    int errLine = 0 , errColumn = 0;
    bOpen = document.setContent(&fileXml,false,&strErr,&errLine,&errColumn);
    if(!bOpen)
    {
        fileXml.close();
        return T_FALSE;
    }
    fileXml.close();
    if(document.isNull())
        return T_FALSE;

    QDomElement root = document.documentElement();
    if(root.isNull())
        return T_FALSE;

    QDomElement item = root.firstChildElement();
    if(item.isNull())
        return T_FALSE;
    while(!item.isNull())
    {
        if(item.hasAttribute("name") &&
                item.hasAttribute("id") &&
                item.hasAttribute("loadorder") &&
                item.hasAttribute("unloadorder") &&
                item.hasAttribute("dllpath"))
        {
            TTmUI* pTmUI = new TTmUI;
            pTmUI->name = item.attribute("name");
            pTmUI->lUiId = item.attribute("id").toLong();
            pTmUI->lLoadOrder = item.attribute("loadorder").toLong();
            pTmUI->lUnloadOrder = item.attribute("unloadorder").toLong();
            pTmUI->strDllPath = item.attribute("dllpath");
            pTmUI->pDll = NULL;
            pTmUI->pMgr = NULL;

            ITModelBase* pModelBase = NULL;
            if(QFile::exists(pTmUI->strDllPath))
            {
                pTmUI->pDll = new QLibrary(pTmUI->strDllPath);
                if(pTmUI->pDll->load())
                {
                    typedef ITModelBase* (*GetInstance)(ITFramework*);
                    GetInstance pGetInstance = (GetInstance)pTmUI->pDll->resolve("GetInstance");
                    if(pGetInstance)
                        pModelBase = pGetInstance(m_pFramework);
                }
            }
            m_pUIList.push_back(pTmUI);

            if(NULL != pModelBase)
            {
                TTmUiModel* pTmModel = new TTmUiModel;
                pTmModel->lUiId = pTmUI->lUiId;
                pTmModel->pModel = pModelBase;
                m_pModelMap[pTmModel->lUiId] = pTmModel;
            }
        }

        item = item.nextSiblingElement();
    }

    return T_OK;
}

TRESULT TUiMgr::UnInit()
{
    qDebug() << "TUiMgr::UnInit()";
    if(!m_pModelMap.empty())
    {
        TTmUiModelMap::iterator itr = m_pModelMap.begin();
        while(m_pModelMap.end() != itr)
        {
            TTmUiModel* pTmModel = itr->second;
            if(pTmModel)
                SAFE_DELETE(pTmModel);

            ++itr;
        }

        m_pModelMap.clear();
    }
    if(!m_pUIList.empty())
    {
        TTmUIList::iterator itr = m_pUIList.begin();
        while(m_pUIList.end() != itr)
        {
            TTmUI* pTmUI = *itr;
            if(pTmUI && pTmUI->pDll && pTmUI->pDll->isLoaded())
                pTmUI->pDll->unload();
            SAFE_DELETE(pTmUI->pDll);
            SAFE_DELETE(pTmUI);

            ++itr;
        }

        m_pUIList.clear();
    }

    return T_OK;
}

TRESULT TUiMgr::SetFramework(ITFramework *pFrm)
{
    m_pFramework = pFrm;
    m_pFramework->GetLogger(&m_pLogger);
    return T_OK;
}

TRESULT TUiMgr::GetUiFromId(unsigned long lUiId, ITModelBase **ppModel)
{
    if(m_pModelMap.empty())
        return T_FALSE;

    TTmUiModelMap::iterator itr = m_pModelMap.find(lUiId);
    if(m_pModelMap.end() == itr)
        return T_FALSE;

    *ppModel = ((TTmUiModel*)itr->second)->pModel;
    return T_OK;
}

TRESULT TUiMgr::Find(unsigned long lUiId, ITModelBase **ppModel)
{
    if(m_pModelMap.empty())
        return T_FALSE;
    TTmUiModelMap::iterator itr = m_pModelMap.find(lUiId);
    if(m_pModelMap.end() == itr)
    {
        ITModelBase *pModelBase = NULL;
        TTmUIList::iterator itrLst = m_pUIList.begin();
        while(m_pUIList.end() != itrLst)
        {
            TTmUI *pUI = *itrLst;
            if(pUI && pUI->lUiId == lUiId && !pUI->pDll)
            {
                if(pUI->pDll)
                {
                    if(pUI->pDll->load())
                    {
                        typedef ITModelBase* (*GetInstance)(ITFramework*);
                        GetInstance pGetInstance = (GetInstance)pUI->pDll->resolve("GetInstance");
                        if(pGetInstance)
                            pModelBase = pGetInstance(m_pFramework);
                    }
                }

                if(pModelBase)
                {
                    TTmUiModel *pTmModel = new TTmUiModel;
                    pTmModel->lUiId = lUiId;
                    pTmModel->pModel = pModelBase;
                    m_pModelMap[pTmModel->lUiId] = pTmModel;
                }
                break;
            }

            ++itrLst;
        }
        *ppModel = pModelBase;
    }
    else
    {
        *ppModel = ((TTmUiModel*)itr->second)->pModel;
    }
    return T_OK;
}
